package dao;

import utils.QueryBuilder;
import beans.QueryInitializerBeanLocal;
import beans.QueryInitializerBeanLocalHome;
import common.*;
import database.DatabaseException;
import database.DatabaseNumber;
import database.DatabaseText;
import java.sql.*;
import java.util.*;
import javax.naming.InitialContext;
import parsers.ResultSetWrapParser;
import templates.*;
import utils.ResultSetWrap;

public class EntityDAO {

    private Application app;
    private short source;

    public static int counter = 0;

    public EntityDAO() {
        app = Application.getInstance();
        source = 0;
    }

    public EntityDAO(short source) {
        this();
        this.source = source;
    }

    public void bind(short source) {
        this.source = source;
    }
    private Collection<EntityPresentation> getCollection(ResultSetWrap rws) throws SQLException {
        Collection<EntityPresentation> container = new LinkedList<EntityPresentation>();
        while (rws.next()) {
            Entity e = new Entity(source);
            e.parse(new ResultSetWrapParser(rws));
            container.add(e);
        }
        return container;
    }

    public EntityPresentation findByPrimaryKey(String primaryKey) throws DatabaseException {
        ++counter;
        QueryInitializerBeanLocal pSlocBean = null;
        try {
            InitialContext ic = new InitialContext();
            QueryInitializerBeanLocalHome lochome = (QueryInitializerBeanLocalHome) ic.lookup("java:comp/env/ejb/QueryInitializer");
            pSlocBean = lochome.create();
            QueryBuilder qB = new QueryBuilder();

            Template template = app.getTemplate(source);
            DatabaseNumber dn = new DatabaseNumber();
            dn.setValue(primaryKey);
            pSlocBean.init(qB.constractSelectQuery(template, null, true),app.getConnectionString());
            pSlocBean.setParam(dn.getValue().getClass().getSimpleName(), dn.toString(), 1);
            ResultSetWrap rws=pSlocBean.resultQuery();
            if (rws.next()) {
                Entity e = new Entity(source);
                e.parse(new ResultSetWrapParser(rws));
                return e;
            } else {
                return null;
            }
        } catch (Exception ex) {
            throw new DatabaseException(ex);
        }
    }

    public Iterable<EntityPresentation> findAll() throws DatabaseException {
        ++counter;
        QueryInitializerBeanLocal pSlocBean = null;
        try {
            QueryBuilder qB = new QueryBuilder();
            InitialContext ic = new InitialContext();
            QueryInitializerBeanLocalHome lochome = (QueryInitializerBeanLocalHome) ic.lookup("java:comp/env/ejb/QueryInitializer");
            pSlocBean = lochome.create();

            Template template = app.getTemplate(source);
            pSlocBean.init(qB.constractSelectQuery(template, null, false),app.getConnectionString());
            Collection<EntityPresentation> container = getCollection(pSlocBean.resultQuery());
            return container;
        } catch (Exception ex) {
            throw new DatabaseException(ex);
        } 
    }

    public Iterable<EntityPresentation> fastFindAll() throws DatabaseException {
        Iterable<EntityPresentation> container = null;
        try {
            QueryBuilder qB = new QueryBuilder();
            EntityCash.capture();
            Iterable<Short> list = EntityCash.analyze(source);
            InitialContext ic = new InitialContext();
            QueryInitializerBeanLocalHome lochome = (QueryInitializerBeanLocalHome) ic.lookup("java:comp/env/ejb/QueryInitializer");
            QueryInitializerBeanLocal pSlocBean = lochome.create();
            for (short n: list) {
                pSlocBean.init(qB.constractSelectQuery(app.getTemplate(n), null, false),app.getConnectionString());
                EntityCash.setRawCash(n, pSlocBean.resultQuery());
                ++counter;
            }
            EntityCash.parse();
            container = EntityCash.getCollection(source);
            EntityCash.release();
            return container;
        } catch(Exception ex) {
            throw new DatabaseException(ex);
        } finally {
            EntityCash.release();
        }
    }

    public Iterable<EntityPresentation> findBy(short uid, String query) throws DatabaseException {
        QueryInitializerBeanLocal pSlocBean = null;
        try {
            InitialContext ic = new InitialContext();
            QueryInitializerBeanLocalHome lochome = (QueryInitializerBeanLocalHome) ic.lookup("java:comp/env/ejb/QueryInitializer");
            pSlocBean = lochome.create();
            QueryBuilder qB = new QueryBuilder();

            Template template = app.getTemplate(source);
            pSlocBean.init(qB.constractSelectQuery(template, uid, false),app.getConnectionString());
            DatabaseText dT = new DatabaseText();
            dT.setValue(query);
            pSlocBean.setParam(dT.getValue().getClass().getSimpleName(), dT.toString(), 1);
            Collection<EntityPresentation> container = getCollection(pSlocBean.resultQuery());
            return container;
        } catch (Exception ex) {
            throw new DatabaseException(ex);
        } 
    }

    public void create(EntityPresentation e) throws DatabaseException {
        QueryInitializerBeanLocal pSlocBean = null;
        try {
            InitialContext ic = new InitialContext();
            QueryInitializerBeanLocalHome lochome = (QueryInitializerBeanLocalHome) ic.lookup("java:comp/env/ejb/QueryInitializer");
            pSlocBean = lochome.create();
            QueryBuilder qB = new QueryBuilder();

            Entity eu = (Entity) e;
            Template template = app.getTemplate(source);
            pSlocBean.init(qB.constractInsertQuery(template),app.getConnectionString());
            Iterator<Property> it = eu.getPropertyCollection().iterator();
            int i = 1;
            while (it.hasNext()) {
                Property pt = it.next();
                if (!pt.getTemplate().isPrimaryKey()) {
                    pSlocBean.setParam(pt.getValue().getValue().getClass().getSimpleName(), pt.getValue().toString(), i);
                    i++;
                }
            }
            pSlocBean.resultUpdate();
        } catch (Exception ex) {
            throw new DatabaseException(ex);
        } 
    }

    public void update(EntityPresentation e) throws DatabaseException {
        QueryInitializerBeanLocal pSlocBean = null;
        try {
            InitialContext ic = new InitialContext();
            QueryInitializerBeanLocalHome lochome = (QueryInitializerBeanLocalHome) ic.lookup("java:comp/env/ejb/QueryInitializer");
            pSlocBean = lochome.create();
            QueryBuilder qB = new QueryBuilder();

            Entity eu = (Entity) e;
            Template template = app.getTemplate(source);
            pSlocBean.init(qB.constractUpdateQuery(template),app.getConnectionString());
            Iterator<Property> it = eu.getPropertyCollection().iterator();
            int i = 1;
            Property forUpdate = null;
            while (it.hasNext()) {
                Property pt = it.next();
                if (!pt.getTemplate().isPrimaryKey()) {
                    pSlocBean.setParam(pt.getValue().getValue().getClass().getSimpleName(), pt.getValue().toString(), i);
                    i++;
                } else {
                    forUpdate = pt;
                }
            }
            pSlocBean.setParam(forUpdate.getValue().getValue().getClass().getSimpleName(), forUpdate.getValue().toString(), i);
            pSlocBean.resultUpdate();
        } catch (Exception ex) {
            throw new DatabaseException(ex);
        }
    }

    public void delete(EntityPresentation e) throws DatabaseException {
        QueryInitializerBeanLocal pSlocBean = null;
        try {
            InitialContext ic = new InitialContext();
            QueryInitializerBeanLocalHome lochome = (QueryInitializerBeanLocalHome) ic.lookup("java:comp/env/ejb/QueryInitializer");
            pSlocBean = lochome.create();
            QueryBuilder qB = new QueryBuilder();

            Entity deleted = (Entity) e;
            Template template = app.getTemplate(source);
            pSlocBean.init(qB.constractDeleteQuery(template),app.getConnectionString());
            Iterator<Property> it = deleted.getPropertyCollection().iterator();
            while (it.hasNext()) {
                Property pt = it.next();
                if (pt.getTemplate().isPrimaryKey()) {
                    pSlocBean.setParam(pt.getValue().getValue().getClass().getSimpleName(), pt.getValue().toString(), 1);
                    break;
                }
            }
            pSlocBean.resultUpdate();
        } catch (Exception ex) {
            throw new DatabaseException(ex);
        } finally {
        }
    }
}
